/**
 * Copyright (c) 2012-2014, Yang Yang <cntototo@gmail.com>
 *
 * This software may be distributed under the terms of the New BSD License.
 * See README for more details.
 */

#ifndef EVENT_H
#define EVENT_H

#include "def.h"
#include "if_manager.h"

/**
 * enum reg_change_initiator -- Initiator of regulatory change
 */
enum reg_change_initiator {
	REGDOM_SET_BY_CORE = 0,
	REGDOM_SET_BY_USER,
	REGDOM_SET_BY_DRIVER,
	REGDOM_SET_BY_COUNTRY_IE
};

/**
 * enum wfs_event_type -- Event type for wfs_process_event() calls
 */
enum wfs_event_type {
	/** Unknown event */
	EVT_UNKNOWN = 0,

	/**
	 * EVT_ASSOC -- Association completed successfully
	 *
	 * This event should be delivered when the driver completes IEEE 802.11
	 * association or reassociation successfully.
	 */
	EVT_ASSOC,

	/**
	 * EVT_ASSOC_REJECT -- Association is rejected
	 *
	 * This event should be delivered when (re)association attempt is
	 * rejected by AP.
	 */
	EVT_ASSOC_REJECT,

	/**
	 * EVT_ASSOC_TIMEOUT -- Association timed out
	 *
	 * This event should be delivered when (re)association attempt timed
	 * out.
	 */
	EVT_ASSOC_TIMEOUT,

	/**
	 * EVT_AUTH -- Authentication completed successfully
	 *
	 * This event should be delivered when authentication is completed.
	 * This is only used if the driver supports separate authentication
	 * step.
	 */
	EVT_AUTH,

	/**
	 * EVT_AUTH_TIMEOUT -- Authentication timed out
	 *
	 * This event should be delivered when authentication attempt timed out.
	 */
	EVT_AUTH_TIMEOUT,

	/**
	 * EVT_CANCEL_ROC -- Remain-on-channel completed
	 *
	 * This event should be delivered when driver completed
	 * remain-on-channel. Then, driver may not be available on the
	 * requested channel anymore.
	 */
	EVT_CANCEL_ROC,

	/**
	 * EVT_CH_SWITCH -- Channel is switched in AP mode
	 *
	 * This event should be delivered when driver switched operating channel
	 * in AP mode.
	 */
	EVT_CH_SWITCH,

	/**
	 * EVT_CONN_FAIL -- Connection failure
	 *
	 * This event should be delivered when driver reported a connection
	 * failure with the specified client.
	 */
	EVT_CONN_FAIL,

	/**
	 * EVT_DEAUTH -- Deauthentication event
	 *
	 * This event should be delivered when receiving deauthentication
	 * frame.
	 */
	EVT_DEAUTH,

	/**
	 * EVT_DEL_STATION -- Peer is removed
	 *
	 * This event should be delivered when peer is removed.
	 */
	EVT_DEL_STATION,

	/**
	 * EVT_DFS_RADAR_DETECTED -- Radar is detected
	 *
	 * This event should be delivered when a radar is detected on the
	 * supplied frequency.
	 */
	EVT_DFS_RADAR_DETECTED,

	/**
	 * struct EVT_DFS_CAC_ABORTED -- CAC has been aborted
	 *
	 * This event should be delivered when channel availablity check has
	 * been aborted.
	 */
	EVT_DFS_CAC_ABORTED,

	/**
	 * EVT_DFS_CAC_FINISHED -- CAC has been completed
	 *
	 * This event should be delivered when channel availablity check has
	 * been completed.
	 */
	EVT_DFS_CAC_FINISHED,

	/**
	 * EVT_DFS_NOP_FINISHED -- NOP is over
	 *
	 * This event should be delivered when non-occupancy period is over.
	 */
	EVT_DFS_NOP_FINISHED,

	/**
	 * EVT_DISASSOC -- Disassociation event
	 *
	 * This event should be delivered when receiving disassociation frame.
	 */
	EVT_DISASSOC,

	/**
	 * EVT_MICHAEL_MIC_FAIL -- Michael MIC (TKIP) failure
	 *
	 * This event should be delivered when a Michael MIC error is detected.
	 */
	EVT_MICHAEL_MIC_FAIL,

	/**
	 * EVT_NEW_STATION -- Authentication can be started with peer
	 *
	 * This event should be delivered when protected frames with peer could
	 * be exchanged.
	 */
	EVT_NEW_STATION,

	/**
	 * EVT_PEER_LOW_ACK -- Peer does not acked packets
	 *
	 * This event should be delivered when many consecutive packets were
	 * not acknowledged by the peer.
	 */
	EVT_PEER_LOW_ACK,

	/**
	 * EVT_PROBE_CLIENT_OK -- Probe client (null data) frame is acked
	 *
	 * This event should be delivered when the station responded to the
	 * probe client (null data) frame.
	 */
	EVT_PROBE_CLIENT_OK,

	/**
	 * EVT_REG_CHANGE -- Regulatory domain is changed
	 *
	 * This event should be delivered when regulatory domain is changed.
	 */
	EVT_REG_CHANGE,

	/**
	 * EVT_RX_MGMT -- RX a management frame
	 *
	 * This event should be delivered when RX a management frame.
	 */
	EVT_RX_MGMT,

	/**
	 * EVT_ROC -- Remain-on-channel is started
	 *
	 * This event should be delivered when diver started remain-on-channel.
	 */
	EVT_ROC,

	/**
	 * EVT_SCAN_RESULTS -- Scan results available
	 *
	 * This event should be delivered when scan results are available to
	 * be fetched.
	 */
	EVT_SCAN_RESULTS,

	/**
	 * EVT_SCHED_SCAN_STOPPED -- Scheduled scan is stopped
	 *
	 * This event should be delivered when the scheduled scan is stopped.
	 */
	EVT_SCHED_SCAN_STOPPED,

	/**
	 * EVT_SIGNAL_CHANGE -- Signal strength is changed
	 *
	 * This event should be delivered when the signal strength is changed.
	 */
	EVT_SIGNAL_CHANGE,

	/**
	 * EVT_START_SCHED_SCAN -- Scheduled scan is started
	 *
	 * This event should be delivered when the scheduled scan is started.
	 */
	EVT_START_SCHED_SCAN,

	/**
	 * EVT_STOP_AP -- AP operation is stopped
	 *
	 * This event should be delivered when driver cannot maintain its AP
	 * operation.
	 */
	EVT_STOP_AP,

	/**
	 * EVT_TDLS -- Requested TDLS operation
	 *
	 * This event should be delivered when a TDLS operation is requested to
	 * be performed.
	 */
	EVT_TDLS,

	/**
	 * EVT_TRIGGER_SCAN -- Scan is triggered
	 *
	 * This event should be delivered when driver triggered scan.
	 */
	EVT_TRIGGER_SCAN,

	/**
	 * EVT_TX_STATUS -- Frame TX status is reported
	 *
	 * This event should be delivered when frame TX status is reported.
	 */
	EVT_TX_STATUS,

	/**
	 * EVT_UNPROT_DEAUTH -- Unprotected deauthentication frame received
	 *
	 * This event should be delivered when a deauth frame is dropped due to
	 * it not being protected (MFP/IEEE 802.11w).
	 */
	EVT_UNPROT_DEAUTH,

	/**
	 * EVT_UNPROT_DISASSOC -- Unprotected disassociation frame received
	 *
	 * This event should be delivered when a disassoc frame is dropped due
	 * to it not being protected (MFP/IEEE 802.11w)
	 */
	EVT_UNPROT_DISASSOC,
};

/**
 * union wfs_event_data -- Event data for wfs_process_event()
 */
union wfs_event_data {
	/**
	 * struct assoc_data -- Data for EVT_ASSOC event
	 */
	struct assoc_data {
		/** Is reassociation or association */
		u8 reassoc;
		/** (Re)Association request IE */
		const u8 *req_ie;
		/** Length of req_ie */
		u32 req_ie_len;
		/** (Re)Association response IE */
		const u8 *resp_ie;
		/** Length of resp_ie */
		u32 resp_ie_len;
		/** Beacon or Probe response IE */
		const u8 *beacon_ie;
		/** Length of beacon_ie */
		u32 beacon_ie_len;
		/** Frequency of operating channel in MHz */
		u32 freq;
		/** Station address (for AP mode) */
		u8 addr[ETH_ALEN];
	} assoc;

	/**
	 * struct assoc_reject_data -- Data for EVT_ASSOC_REJECT event
	 */
	struct assoc_reject_data {
		/** BSSID of AP that rejected association */
		u8 bssid[ETH_ALEN];
		/** (Re)Association response IE */
		const u8 *resp_ie;
		/** Length of resp_ie */
		u32 resp_ie_len;
		/** Status code from (Re)association response */
		u16 status_code;
	} assoc_reject;

	/**
	 * struct auth_data -- Data for EVT_AUTH event
	 */
	struct auth_data {
		u8 peer[ETH_ALEN];
		u8 bssid[ETH_ALEN];
		u16 auth_type;
		u16 auth_transaction;
		u16 status_code;
		const u8 *ie;
		u32 ie_len;
	} auth;

	/**
	 * struct ch_switch_data -- Data for EVT_CH_SWITCH event
	 */
	struct ch_switch_data {
		/** Frequency of new channel in MHz */
		u32 freq;
		/** Is an HT channel */
		u8 ht;
		/** Secondary channel offset */
		int offset;
		/** Channel width */
		enum wfs_ch_width ch_width;
		/** Center frequency 1 */
		u32 c_freq1;
		/** Center frequency 2 */
		u32 c_freq2;
	} ch_switch;

	/**
	 * struct conn_fail_data -- Data for EVT_CONN_FAIL event
	 */
	struct conn_fail_data {
		u8 addr[ETH_ALEN];
		enum {
			MAX_CLIENTS,
			BLOCKED_CLIENT,
		} reason;
	} conn_fail;

	/**
	 * struct deauth_data -- Data for EVT_DEAUTH event
	 */
	struct deauth_data {
		/** Reason code */
		u16 reason_code;
		/** Optional IE in deauthentication frame */
		const u8 *ie;
		/** Length of ie */
		u32 ie_len;
		/** Is locally generated */
		u8 local;
		/** Station address (for AP mode) */
		u8 addr[ETH_ALEN];
	} deauth;

	/**
	 * struct del_sta_data -- Data for EVT_DEL_STATION event
	 */
	struct del_sta_data {
		u8 peer[ETH_ALEN];
	} del_sta;

	/**
	 * struct dfs_data -- Data for EVT_DFS_* events
	 */
	struct dfs_data {
		/** Frequency of new channel in MHz */
		u32 freq;
		/** Is an HT channel */
		u8 ht;
		/** Secondary channel offset */
		int offset;
		/** Channel width */
		enum wfs_ch_width ch_width;
		/** Center frequency 1 */
		u32 c_freq1;
		/** Center frequency 2 */
		u32 c_freq2;
	} dfs;

	/**
	 * struct disassoc_data -- Data for EVT_DISASSOC event
	 */
	struct disassoc_data {
		/** Reason code */
		u16 reason_code;
		/** Optional IE in disassociation frame */
		const u8 *ie;
		/** Length of ie */
		u32 ie_len;
		/** Is locally generated */
		u8 local;
		/** Station address (for AP mode) */
		u8 addr[ETH_ALEN];
	} disassoc;

	/**
	 * struct michael_mic_fail_data -- Data for EVT_MICHAEL_MIC_FAIL event
	 */
	struct michael_mic_fail_data {
		/** Source address */
		u8 src[ETH_ALEN];
		/** Is unicast or not */
		u8 unicast;
	} michael_mic_fail;

	/**
	 * struct new_sta_data -- Data for EVT_NEW_STATION event
	 */
	struct new_sta_data {
		u8 peer[ETH_ALEN];
	} new_sta;

	/**
	 * struct peer_low_ack_data -- Data for EVT_PEER_LOW_ACK event
	 */
	struct peer_low_ack_data {
		u8 addr[ETH_ALEN];
	} peer_low_ack;

	/**
	 * struct probe_client_data -- Data for EVT_PROBE_CLIENT_OK event
	 */
	struct probe_client_data {
		u8 addr[ETH_ALEN];
	} probe_client;

	/**
	 * struct reg_change_data -- Data for EVT_REG_CHANGE event
	 */
	struct reg_change_data {
		enum reg_change_initiator initiator;
	} reg_change;

	/**
	 * struct roc_data -- Data for EVT_ROC and EVT_CANCEL_ROC events
	 */
	struct roc_data {
		/** Frequency in MHz */
		u32 freq;
		/** Duration to remain on channel in msecs */
		u32 dur;
	} roc;

	/**
	 * struct rx_mgmt_data -- Data for EVT_RX_MGMT event
	 */
	struct rx_mgmt_data {
		/** Frame data */
		const u8 *frame;
		/** Length of frame */
		u32 frame_len;
		/** Data rate */
		u32 rate;
		/** Frequency of the RX frame in MHz */
		u32 freq;
		/** Signal strength in dBm */
		u32 signal;
	} rx_mgmt;

	/**
	 * struct scan_data -- Data for EVT_SCAN_RESULTS event
	 */
	struct scan_data {
		/** Is the scan aborted */
		u8 aborted;
		/** Scanned frequencies in MHz (NULL = all channels) */
		const u32 *freqs;
		/** Number of frequencies */
		u32 freq_num;
		/** Scanned devices */
		struct scanned_device {
			/** NULL or zero-length means wildcard SSID */
			const u8 *ssid;
			/** Length of SSID in bytes */
			u32 ssid_len;
		} devices[MAX_SCAN_DEVICES];
		/** Number of devices */
		u32 device_num;
	} scan;

	/**
	 * struct sig_data -- Data for EVT_SIGNAL_CHANGE event
	 */
	struct sig_data {
		/** Frequency in MHz */
		u32 freq;
		/** Center frequency 1 */
		u32 c_freq1;
		/** Center frequency 2 */
		u32 c_freq2;
		/** Is RSSI above threshold */
		u8 above_threshold;
		/** Current signal */
		u8 sig;
		/** Average signal */
		u8 avg_sig;
		/** Current noise */
		u8 noise;
		/** Current TX rate */
		u16 tx_rate;
		/** Channel width */
		enum wfs_ch_width ch_width;
	} sig_change;

	/**
	 * struct tdls_data -- Data for EVT_TDLS event
	 */
	struct tdls_data {
		/** MAC address of peer */
		u8 peer[ETH_ALEN];
		/** TDLS operation */
		enum wfs_tdls_oper oper;
		/** Reason code for TDLS teardown */
		u16 reason_code;
	} tdls;

	/**
	 * struct timeout_data -- Data for EVT_ASSOC_TIMEOUT and
	 * EVT_AUTH_TIMEOUT events
	 */
	struct timeout_data {
		u8 addr[ETH_ALEN];
	} timeout;

	/**
	 * struct tx_status_data -- Data for EVT_TX_STATUS event
	 */
	struct tx_status_data {
		/** Frame control type */
		u16 type;
		/** Frame control subtype */
		u16 stype;
		/** Destination address */
		u8 dst[ETH_ALEN];
		/** Frame data */
		const u8 *frame;
		/** Length of frame */
		u32 frame_len;
		/** Is frame acked */
		u8 ack;
	} tx_status;

	/**
	 * struct unprot_deauth_data -- Data for EVT_UNPROT_DEAUTH event
	 */
	struct unprot_deauth_data {
		/** Source address */
		u8 sa[ETH_ALEN];
		/** Destination address */
		u8 da[ETH_ALEN];
		/** Reason code */
		u16 reason_code;
	} unprot_deauth;

	/**
	 * struct unprot_disassoc_data -- Data for EVT_UNPROT_DISASSOC event
	 */
	struct unprot_disassoc_data {
		/** Source address */
		u8 sa[ETH_ALEN];
		/** Destination address */
		u8 da[ETH_ALEN];
		/** Reason code */
		u16 reason_code;
	} unprot_disassoc;
};

enum wfs_internal_err
wfs_process_event(struct wfs_iface *cur_if, enum wfs_event_type evt_type,
		union wfs_event_data *event);

#endif /* EVENT_H */
